﻿using System;
using System.Diagnostics;
using System.Net;
using System.Web;
using EPiBoost.Core.Infrastructure.Interfaces.Providers;
using EPiBoost.Core.Infrastructure.Interfaces.Repositories;
using EPiBoost.Core.Infrastructure.Model;

namespace EPiBoost.Core.Infrastructure.Providers
{
	public class ExceptionLogProvider : IExceptionLogProvider
	{

		private const string _ClassName = "ExceptionLogProvider";

		private IExceptionLogRepository _repository;

		enum ExceptionCategories
		{
			HttpException
		}

		private const int _Priority_Exception = 1;
		private const int _Priority_HttpException = 2;
		private const int _Priority_Information = 5;

		public ExceptionLogProvider()
		{
			_repository = Global.ExceptionLogRepository;
		}

		public void LogHttpException(HttpContext context)
		{
			if(context.Response.StatusCode != (int)HttpStatusCode.OK)
			{
				var logItem = new LogItem(context)
					{
						Category = ExceptionCategories.HttpException.ToString(),
						Priority = _Priority_HttpException
					};

				_repository.Add(logItem);
			}
		}

		public void LogException(Exception ex, HttpContext context = null)
		{
			context = context ?? HttpContext.Current;

			var logItem = new LogItem(context)
			{
				Exception = ex.InnerException != null ? ex.InnerException.Message : ex.Message,
				Priority = _Priority_Exception,
				SourceMethod = GetCallingMethodName()
			};

			_repository.Add(logItem);
		}

		public void LogInformation(string message, string category, HttpContext context = null)
		{
			context = context ?? HttpContext.Current;

			var logItem = new LogItem(context)
			{
				Message = message,
				Category = category, 
				Priority = _Priority_Information,
				SourceMethod = GetCallingMethodName()
			};

			_repository.Add(logItem);
		}

		private string GetCallingMethodName()
		{
			var stackTrace = new StackTrace();
			for (int i = 0; i < stackTrace.FrameCount; i++)
			{
				if (stackTrace.GetFrame(i).GetMethod().ReflectedType.Name != _ClassName)
				{
					var m = stackTrace.GetFrame(i).GetMethod();
					return string.Format("{0}.{1}", m.ReflectedType.FullName, m.Name);
				}
			}
			return null;
		}
	}
}
